library(data.table)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
data.table 1.12.8 using 2 threads (see ?getDTthreads).  Latest news: r-datatable.com
library(ggplot2)
Registered S3 method overwritten by 'dplyr':
  method           from
  print.rowwise_df     
library(beanplot) # for beanplots
library(gridExtra) # to combine ggplots together
library(grid) # to combine ggplots together


knitr::opts_knit$set(root.dir = rprojroot::find_rstudio_root_file()) # tell RStudio to use project root directory as the root for this notebook. Needed since we are storing code in a separate directory.

Load data

# BioTime
load('data/biotime_blowes/bt_malin.Rdata')
bt <- data.table(bt_malin); rm(bt_malin)

# Temperature average, trends, and seasonality
temperature <- fread('output/temperature_byrarefyID.csv.gz')

# microclimates
microclim <- fread('output/microclimates.csv.gz', drop = 1)

# NPP
npp <- fread('output/npplandocean.csv.gz')

# Body size
bs <- fread('output/mass_byrarefyid.csv.gz', drop = 1)
bs[, ':='(STUDY_ID = NULL, REALM = NULL, taxa_mod = NULL)] # remove unnecessary columns 

# Mobility
speed <- fread('output/speed_byrarefyID.csv.gz', drop = 1)
speed[, ':='(STUDY_ID = NULL, REALM = NULL, taxa_mod = NULL)] # remove unnecessary columns 

# Lifespan
lsp <- fread('output/lifespan_byrarefyID.csv.gz')

# CTI
cti <- fread('output/cti_byrarefyID.csv.gz')
    
# consumer vs. producer
cons <- fread('output/metab_feed_byspecies.csv.gz')
consfrac <- cons[, .(consfrac = sum(feeding == 'consumer')/.N), by = rarefyID] # fraction of species in each study that are consumers

# richness
rich <- fread('output/richness_by_rarefyID.csv.gz') # number of species

# endotherm vs. ectotherm
endo <- fread('output/metab_feed_byspecies.csv.gz') # endotherm vs. ectotherm classifications
endofrac <- endo[, .(endofrac = sum(metab != 'ecto')/.N), by = rarefyID]
rm(endo)

# human impact
human <- fread('output/humanimpact_by_rarefyID.csv.gz')

# %veg
veg <- as.data.table(readRDS('output/vct_by_rarefyID.rds'))
veg[, veg := (`tree cover % (mean)` + 0.5 * `non-tree veg. % (mean)`)/100] # veg index from 0 (all non-veg) to 1 (all tree). Non-tree veg counts as 0.5.

Plot a turnover example

#bt[, .(n = .N), by = rarefyID][n > 50,]

ggplot(bt[rarefyID == '339_1085477'], aes(YEAR, Jtu_base)) +
    geom_point() +
    geom_smooth(method = 'lm') +
    xlab('Year') + ylab('Jaccard dissimilarity')

Compare covariates across realms

i <- trends[, !duplicated(rarefyID)]; sum(i)
[1] 53013
par(mfrow=c(5,3))
beanplot(rarefyID_y ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Latitude (degN)', ll = 0.05)
beanplot(tempave ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Temperature (degC)', ll = 0.05)
beanplot(tempave_metab ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Metabolic Temperature (degC)', ll = 0.05, bw = 'nrd0') # nrd0 bandwidth to calculation gap
beanplot(seas ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Seasonality (degC)', ll = 0.05)
beanplot(microclim ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Microclimates (degC)', ll = 0.05)
log="y" selected
beanplot(temptrend ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Temperature trend (degC/yr)', ll = 0.05)
beanplot(mass_mean_weight ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Mass (g)', ll = 0.05, log = 'y')
beanplot(speed_mean_weight +1 ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Speed (km/hr)', ll = 0.05, log = 'y')
beanplot(lifespan_mean_weight ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Lifespan (yr)', ll = 0.05, log = 'y')
#beanplot(consfrac ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Consumers (fraction)', ll = 0.05, log = '') # too sparse
#beanplot(endofrac ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Endotherms (fraction)', ll = 0.05, log = '') # too sparse
beanplot(Nspp ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Number of species', ll = 0.05, log = 'y')
beanplot(thermal_bias ~ REALM, data = trends[i & !is.na(thermal_bias),], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Thermal bias (degC)', ll = 0.05)
beanplot(npp ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'NPP', ll = 0.05)
log="y" selected
beanplot(veg ~ REALM, data = trends[i & REALM !='Marine',], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'NPP', ll = 0.05)
beanplot(human_bowler ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Human impact score (Bowler)', ll = 0.05)
beanplot(human_footprint.sc ~ REALM, data = trends[i,], what = c(1,1,1,1), col = c("#CAB2D6", "#33A02C", "#B2DF8A"), border = "#CAB2D6", ylab = 'Human impact score (Venter/Halpern', ll = 0.05)

Marine are in generally warmer locations (seawater doesn’t freeze) Marine have much lower seasonality. Marine and freshwater have some very small masses (plankton), but much of dataset is similar to terrestrial. Marine has a lot of slow, crawling organisms, but land has plants. Land also has birds (fast).

Plot turnover vs. explanatory variables

Lines are ggplot smoother fits.

Strong trends with temperature change, but trends are pretty symmetric around no trend in temperature, which implies warming or cooling drives similar degree of community turnover. Some indication of less turnover for larger organisms (mass) Higher turnover on land with higher seasonality? More turnover for shorter-lived organisms? No really clear differences among realms.

Write out

write.csv(trends, gzfile('output/turnover_w_covariates.csv.gz'), row.names = FALSE)

Useful variables

# realm that combined Terrestrial and Freshwater, for interacting with human impact
trends[, REALM2 := REALM]
levels(trends$REALM2) = list(TerrFresh = "Freshwater", TerrFresh = "Terrestrial", Marine = "Marine")

# group Marine invertebrates/plants in with All
trends[, taxa_mod2 := taxa_mod]
trends[taxa_mod == 'Marine invertebrates/plants', taxa_mod2 := 'All']

Log-transform some variables, then center and scale.

trends[, tempave.sc := scale(tempave)]
trends[, tempave_metab.sc := scale(tempave_metab)]
trends[, seas.sc := scale(seas)]
trends[, microclim.sc := scale(log(microclim))]
trends[, temptrend.sc := scale(temptrend, center = FALSE)]
trends[, temptrend_abs.sc := scale(abs(temptrend), center = FALSE)] # do not center, so that 0 is still 0 temperature change
trends[, mass.sc := scale(log(mass_mean_weight))]
trends[, speed.sc := scale(log(speed_mean_weight+1))]
trends[, lifespan.sc := scale(log(lifespan_mean_weight))]
trends[, consumerfrac.sc := scale(consfrac)]
trends[, endothermfrac.sc := scale(endofrac)]
trends[, nspp.sc := scale(log(Nspp))]
trends[, thermal_bias.sc := scale(thermal_bias)]
trends[, npp.sc := scale(log(npp))]
trends[, veg.sc := scale(log(veg+1))]
trends[, human_bowler.sc := scale(log(human_bowler+1)), by = REALM2] # separate scaling by realm
trends[REALM2 == 'TerrFresh', human_footprint.sc := scale(log(human_venter+1))]
trends[REALM2 == 'Marine', human_footprint.sc := scale(log(human_halpern))]

Do the variables look ok?

Unscaled

# histograms to examine
cexmain = 0.6
par(mfrow = c(5,4))
invisible(trends[, hist(minyrBT, main = 'Start year', cex.main = cexmain)])
invisible(trends[, hist(maxyrBT - minyrBT, main = 'Duration (years)', cex.main = cexmain)])
invisible(trends[, hist(nyrBT, main = 'Number of sampled years', cex.main = cexmain)])
invisible(trends[, hist(mass_mean_weight, main = 'Mass (g)', cex.main = cexmain)])
invisible(trends[, hist(speed_mean_weight, main = 'Speed (km/hr)', cex.main = cexmain)])
invisible(trends[, hist(lifespan_mean_weight, main = 'Lifespan (yr)', cex.main = cexmain)])
invisible(trends[, hist(tempave_metab, main = 'Metabolic temperature (°C)', cex.main = cexmain)])
invisible(trends[, hist(consfrac, main = 'Consumers (fraction)', cex.main = cexmain)])
invisible(trends[, hist(endofrac, main = 'Endotherms (fraction)', cex.main = cexmain)])
invisible(trends[, hist(tempave, main = 'Environmental temperature (°C)', cex.main = cexmain)])
invisible(trends[, hist(temptrend, main = 'Temperature trend (°C/yr)', cex.main = cexmain)])
invisible(trends[, hist(seas, main = 'Seasonality (°C)', cex.main = cexmain)])
invisible(trends[, hist(microclim, main = 'Microclimates (°C)', cex.main = cexmain)])
invisible(trends[, hist(Nspp, main = 'Species richness', cex.main = cexmain)])
invisible(trends[, hist(thermal_bias, main = 'Thermal bias (°C)', cex.main = cexmain)])
invisible(trends[, hist(npp, main = 'Net primary productivity', cex.main = cexmain)])
invisible(trends[, hist(veg, main = 'Vegetation index', cex.main = cexmain)])
invisible(trends[, hist(human_bowler, main = 'Human impact score (Bowler)', cex.main = cexmain)])
invisible(trends[, hist(human_venter, main = 'Human impact score (Venter)', cex.main = cexmain)])
invisible(trends[, hist(human_halpern, main = 'Human impact score (Halpern)', cex.main = cexmain)])

Scaled

# histograms to examine
cexmain = 0.6
par(mfrow = c(5,4))
invisible(trends[, hist(tempave.sc, main = 'Environmental temperature (°C)', cex.main = cexmain)])
invisible(trends[, hist(tempave_metab.sc, main = 'Metabolic temperature (°C)', cex.main = cexmain)])
invisible(trends[, hist(seas.sc, main = 'Seasonality (°C)', cex.main = cexmain)])
invisible(trends[, hist(microclim.sc, main = 'log Microclimates (°C)', cex.main = cexmain)])
invisible(trends[, hist(temptrend.sc, main = 'Temperature trend (°C/yr)', cex.main = cexmain)])
invisible(trends[, hist(temptrend_abs.sc, main = 'abs(Temperature trend) (°C/yr)', cex.main = cexmain)])
invisible(trends[, hist(mass.sc, main = 'log Mass (g)', cex.main = cexmain)])
invisible(trends[, hist(speed.sc, main = 'log Speed (km/hr)', cex.main = cexmain)])
invisible(trends[, hist(lifespan.sc, main = 'log Lifespan (yr)', cex.main = cexmain)])
invisible(trends[, hist(consumerfrac.sc, main = 'Consumers (fraction)', cex.main = cexmain)])
invisible(trends[, hist(endothermfrac.sc, main = 'Endotherms (fraction)', cex.main = cexmain)])
invisible(trends[, hist(nspp.sc, main = 'log Species richness', cex.main = cexmain)])
invisible(trends[, hist(thermal_bias.sc, main = 'Thermal bias (°C)', cex.main = cexmain)])
invisible(trends[, hist(npp.sc, main = 'log Net primary productivity', cex.main = cexmain)])
invisible(trends[, hist(veg.sc, main = 'log Vegetation index', cex.main = cexmain)])
invisible(trends[, hist(human_bowler.sc, main = 'log Human impact score (Bowler)', cex.main = cexmain)])
invisible(trends[, hist(human_footprint.sc, main = 'log Human impact score (Venter & Halpern)', cex.main = cexmain)])

Check correlations among variables. Pearson’s r is on the lower diagonal.

panel.cor <- function(x, y, digits = 2, prefix = "", cex.cor, ...)
{
    usr <- par("usr"); on.exit(par(usr))
    par(usr = c(0, 1, 0, 1))
    r <- cor(x, y, use = 'pairwise.complete.obs')
    txt <- format(c(r, 0.123456789), digits = digits)[1]
    txt <- paste0(prefix, txt)
    if(missing(cex.cor)) cex.cor <- 0.8/strwidth(txt)
    text(0.5, 0.5, txt) #, cex = cex.cor * r)
}
pairs(formula = ~ tempave.sc + tempave_metab.sc + seas.sc + microclim.sc + temptrend.sc + temptrend_abs.sc + mass.sc + speed.sc + lifespan.sc + consumerfrac.sc + endothermfrac.sc + nspp.sc + thermal_bias.sc + npp.sc + veg.sc + human_bowler.sc + human_footprint.sc, data = trends, gap = 1/10, cex = 0.2, col = '#00000022', lower.panel = panel.cor)

Mass and lifespan look tightly correlated, but r only 0.56…? Tempave_metab and lifespan don’t look tightly correlated, but r= -0.81 Tempave_metab and speed don’t look tightly correlated, but r= -0.83 Lifespan and speed don’t look tightly correlated, but r = 0.73

LS0tCnRpdGxlOiAiVHVybm92ZXIgY292YXJpYXRlIGRhdGEgcHJlcCIKb3V0cHV0OgogIGdpdGh1Yl9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgpgYGB7ciBzZXR1cH0KbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoYmVhbnBsb3QpICMgZm9yIGJlYW5wbG90cwpsaWJyYXJ5KGdyaWRFeHRyYSkgIyB0byBjb21iaW5lIGdncGxvdHMgdG9nZXRoZXIKbGlicmFyeShncmlkKSAjIHRvIGNvbWJpbmUgZ2dwbG90cyB0b2dldGhlcgoKCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gcnByb2pyb290OjpmaW5kX3JzdHVkaW9fcm9vdF9maWxlKCkpICMgdGVsbCBSU3R1ZGlvIHRvIHVzZSBwcm9qZWN0IHJvb3QgZGlyZWN0b3J5IGFzIHRoZSByb290IGZvciB0aGlzIG5vdGVib29rLiBOZWVkZWQgc2luY2Ugd2UgYXJlIHN0b3JpbmcgY29kZSBpbiBhIHNlcGFyYXRlIGRpcmVjdG9yeS4KYGBgCgojIyMgTG9hZCBkYXRhCmBgYHtyIGxvYWQgZGF0YX0KIyBCaW9UaW1lCmxvYWQoJ2RhdGEvYmlvdGltZV9ibG93ZXMvYnRfbWFsaW4uUmRhdGEnKQpidCA8LSBkYXRhLnRhYmxlKGJ0X21hbGluKTsgcm0oYnRfbWFsaW4pCgojIFRlbXBlcmF0dXJlIGF2ZXJhZ2UsIHRyZW5kcywgYW5kIHNlYXNvbmFsaXR5CnRlbXBlcmF0dXJlIDwtIGZyZWFkKCdvdXRwdXQvdGVtcGVyYXR1cmVfYnlyYXJlZnlJRC5jc3YuZ3onKQoKIyBtaWNyb2NsaW1hdGVzCm1pY3JvY2xpbSA8LSBmcmVhZCgnb3V0cHV0L21pY3JvY2xpbWF0ZXMuY3N2Lmd6JywgZHJvcCA9IDEpCgojIE5QUApucHAgPC0gZnJlYWQoJ291dHB1dC9ucHBsYW5kb2NlYW4uY3N2Lmd6JykKCiMgQm9keSBzaXplCmJzIDwtIGZyZWFkKCdvdXRwdXQvbWFzc19ieXJhcmVmeWlkLmNzdi5neicsIGRyb3AgPSAxKQpic1ssICc6PScoU1RVRFlfSUQgPSBOVUxMLCBSRUFMTSA9IE5VTEwsIHRheGFfbW9kID0gTlVMTCldICMgcmVtb3ZlIHVubmVjZXNzYXJ5IGNvbHVtbnMgCgojIE1vYmlsaXR5CnNwZWVkIDwtIGZyZWFkKCdvdXRwdXQvc3BlZWRfYnlyYXJlZnlJRC5jc3YuZ3onLCBkcm9wID0gMSkKc3BlZWRbLCAnOj0nKFNUVURZX0lEID0gTlVMTCwgUkVBTE0gPSBOVUxMLCB0YXhhX21vZCA9IE5VTEwpXSAjIHJlbW92ZSB1bm5lY2Vzc2FyeSBjb2x1bW5zIAoKIyBMaWZlc3Bhbgpsc3AgPC0gZnJlYWQoJ291dHB1dC9saWZlc3Bhbl9ieXJhcmVmeUlELmNzdi5neicpCgojIENUSQpjdGkgPC0gZnJlYWQoJ291dHB1dC9jdGlfYnlyYXJlZnlJRC5jc3YuZ3onKQogICAgCiMgY29uc3VtZXIgdnMuIHByb2R1Y2VyCmNvbnMgPC0gZnJlYWQoJ291dHB1dC9tZXRhYl9mZWVkX2J5c3BlY2llcy5jc3YuZ3onKQpjb25zZnJhYyA8LSBjb25zWywgLihjb25zZnJhYyA9IHN1bShmZWVkaW5nID09ICdjb25zdW1lcicpLy5OKSwgYnkgPSByYXJlZnlJRF0gIyBmcmFjdGlvbiBvZiBzcGVjaWVzIGluIGVhY2ggc3R1ZHkgdGhhdCBhcmUgY29uc3VtZXJzCgojIHJpY2huZXNzCnJpY2ggPC0gZnJlYWQoJ291dHB1dC9yaWNobmVzc19ieV9yYXJlZnlJRC5jc3YuZ3onKSAjIG51bWJlciBvZiBzcGVjaWVzCgojIGVuZG90aGVybSB2cy4gZWN0b3RoZXJtCmVuZG8gPC0gZnJlYWQoJ291dHB1dC9tZXRhYl9mZWVkX2J5c3BlY2llcy5jc3YuZ3onKSAjIGVuZG90aGVybSB2cy4gZWN0b3RoZXJtIGNsYXNzaWZpY2F0aW9ucwplbmRvZnJhYyA8LSBlbmRvWywgLihlbmRvZnJhYyA9IHN1bShtZXRhYiAhPSAnZWN0bycpLy5OKSwgYnkgPSByYXJlZnlJRF0Kcm0oZW5kbykKCiMgaHVtYW4gaW1wYWN0Cmh1bWFuIDwtIGZyZWFkKCdvdXRwdXQvaHVtYW5pbXBhY3RfYnlfcmFyZWZ5SUQuY3N2Lmd6JykKCiMgJXZlZwp2ZWcgPC0gYXMuZGF0YS50YWJsZShyZWFkUkRTKCdvdXRwdXQvdmN0X2J5X3JhcmVmeUlELnJkcycpKQp2ZWdbLCB2ZWcgOj0gKGB0cmVlIGNvdmVyICUgKG1lYW4pYCArIDAuNSAqIGBub24tdHJlZSB2ZWcuICUgKG1lYW4pYCkvMTAwXSAjIHZlZyBpbmRleCBmcm9tIDAgKGFsbCBub24tdmVnKSB0byAxIChhbGwgdHJlZSkuIE5vbi10cmVlIHZlZyBjb3VudHMgYXMgMC41LgpgYGAKCiMjIyBQbG90IGEgdHVybm92ZXIgZXhhbXBsZQpgYGB7ciBwbG90IHR1cm5vdmVyfQojYnRbLCAuKG4gPSAuTiksIGJ5ID0gcmFyZWZ5SURdW24gPiA1MCxdCgpnZ3Bsb3QoYnRbcmFyZWZ5SUQgPT0gJzMzOV8xMDg1NDc3J10sIGFlcyhZRUFSLCBKdHVfYmFzZSkpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nKSArCiAgICB4bGFiKCdZZWFyJykgKyB5bGFiKCdKYWNjYXJkIGRpc3NpbWlsYXJpdHknKQpgYGAKCiMjIyBBc3NlbWJsZSBkYXRhc2V0IG9mIGJldGEgZGl2ZXJzaXR5IHRyZW5kcyAodGVtcG9yYWwgdHVybm92ZXIpIGFuZCBjb3ZhcmlhdGVzCmBgYHtyIGFzc2VtYmxlIHRyZW5kc30KIyBjYWxjdWxhdGUgdGVtcG9yYWwgdHVybm92ZXIKY2FsY3RyZW5kIDwtIGZ1bmN0aW9uKHksIFlFQVIsIG5tID0gJ3knKXsgIyBmdW5jdGlvbiB0byBjYWxjIHRyZW5kcwogICAgbW9kIDwtIGxtKHkgfiBZRUFSKQogICAgb3V0IDwtIGxpc3QoeSA9IGNvZWYobW9kKVsyXSwgIyBjb2VmIGZvciB0aGUgc2xvcGUKICAgICAgICAgeV9zZSA9IHNxcnQoZGlhZyh2Y292KG1vZCkpKVsyXSkgIyBTRQogICAgbmFtZXMob3V0KSA8LSBjKG5tLCBwYXN0ZTAobm0sICdfc2UnKSkKICAgIHJldHVybihvdXQpCn0KCiMgZnVuY3Rpb24gdG8gY2FsYyB0cmVuZHMsIHJlbW92aW5nIGZpcnN0IHllYXIgd2l0aCAwCmNhbGN0cmVuZHJlbTAgPC0gZnVuY3Rpb24oeSwgWUVBUiwgbm0gPSAneScpewogIGlmKGxlbmd0aChZRUFSKT4yKXsKICAgIG8gPC0gb3JkZXIoWUVBUikKICAgIFlFQVIyIDwtIFlFQVJbb11bMjpsZW5ndGgoWUVBUildCiAgICB5MiA8LSB5W29dWzI6bGVuZ3RoKHkpXQogICAgCiAgICBpZihzdW0oIWlzLm5hKHkyKSkgPj0gMil7ICMgbWFrZSBzdXJlIGVub3VnaCB2YWx1ZXMgdG8gZml0IGEgbGluZQogICAgICBtb2QgPC0gbG0oeTIgfiBZRUFSMikKICAgICAgb3V0IDwtIGxpc3QoeSA9IGNvZWYobW9kKVsyXSwgIyBjb2VmIGZvciB0aGUgc2xvcGUKICAgICAgICAgICAgICAgICAgeV9zZSA9IHNxcnQoZGlhZyh2Y292KG1vZCkpKVsyXSkgIyBTRQogICAgICBuYW1lcyhvdXQpIDwtIGMobm0sIHBhc3RlMChubSwgJ19zZScpKQogICAgICByZXR1cm4ob3V0KQogICAgfSBlbHNlIHsKICAgICAgb3V0IDwtIGxpc3QoeSA9IE5BX3JlYWxfLCB5X3NlID0gTkFfcmVhbF8pCiAgICAgIG5hbWVzKG91dCkgPC0gYyhubSwgcGFzdGUwKG5tLCAnX3NlJykpCiAgICAgIHJldHVybihvdXQpCiAgICB9CiAgICAKICB9IGVsc2UgewogICAgb3V0IDwtIGxpc3QoeSA9IE5BX3JlYWxfLCB5X3NlID0gTkFfcmVhbF8pCiAgICBuYW1lcyhvdXQpIDwtIGMobm0sIHBhc3RlMChubSwgJ19zZScpKQogICAgcmV0dXJuKG91dCkKICB9Cn0KCgpzZXRrZXkoYnQsIFNUVURZX0lELCByYXJlZnlJRCwgWUVBUikKdHJlbmRzIDwtIGJ0WywgY2FsY3RyZW5kKEp0dV9iYXNlLCBZRUFSLCAnSnR1dHJlbmQnKSwgCiAgICBieSA9IC4oUkVBTE0sIEJpb21lLCB0YXhhX21vZCwgU1RVRFlfSUQsIHJhcmVmeUlELCByYXJlZnlJRF94LCByYXJlZnlJRF95KV0gIyBjYWxjdWxhdGUgdHJlbmQgaW4gSmFjY2FyZCB0dXJub3ZlciBmcm9tIGZpcnN0IHllYXIsIHBsdXMgU0VzCnRyZW5kczIgPC0gYnRbLCBjYWxjdHJlbmQoSmJldGFfYmFzZSwgWUVBUiwgJ0piZXRhdHJlbmQnKSwgCiAgICBieSA9IC4ocmFyZWZ5SUQpXSAjIGNhbGN1bGF0ZSB0cmVuZCBpbiB0b3RhbCBKYWNjYXJkJyBiZXRhIGRpdmVyc2l0eSdzIGZyb20gZmlyc3QgeWVhciwgCnRyZW5kczMgPC0gYnRbLCBjYWxjdHJlbmQoMS1Ib3JuX2Jhc2UsIFlFQVIsICdIb3JudHJlbmQnKSwgCiAgICBieSA9IC4ocmFyZWZ5SUQpXSAjIGNhbGN1bGF0ZSB0cmVuZCBpbiBIb3JuLU1vcmlzaXRhIGZyb20gZmlyc3QgeWVhci4gQ29udmVydCB0byBkaXNzaW1pbGFyaXR5LgojdHJlbmRzNCA8LSBidFssIC4oU3RyZW5kID0gY29lZihsbShJKGxvZyhTKSkgfiBZRUFSKSlbMl0pLCBieSA9IC4ocmFyZWZ5SUQpXSAjIHRyZW5kIGluIGxvZyhTKQoKdHJlbmRzNSA8LSBidFssIGNhbGN0cmVuZHJlbTAoSnR1X2Jhc2UsIFlFQVIsICdKdHV0cmVuZHJlbTAnKSwgCiAgICBieSA9IC4ocmFyZWZ5SUQpXSAjIGNhbGN1bGF0ZSB0cmVuZCBpbiBKYWNjYXJkIHR1cm5vdmVyIHdpdGhvdXQgZmlyc3QgeWVhcgp0cmVuZHM2IDwtIGJ0WywgY2FsY3RyZW5kcmVtMChKYmV0YV9iYXNlLCBZRUFSLCAnSmJldGF0cmVuZHJlbTAnKSwgCiAgICBieSA9IC4ocmFyZWZ5SUQpXQp0cmVuZHM3IDwtIGJ0WywgY2FsY3RyZW5kcmVtMCgxLUhvcm5fYmFzZSwgWUVBUiwgJ0hvcm50cmVuZHJlbTAnKSwgCiAgICBieSA9IC4ocmFyZWZ5SUQpXQoKCm55ckJUIDwtICBidFssIC4obnlyQlQgPSBsZW5ndGgoWUVBUiksIAogICAgICAgICAgICAgICAgIG1pbnlyQlQgPSBtaW4oWUVBUiksIAogICAgICAgICAgICAgICAgIG1heHlyQlQgPSBtYXgoWUVBUiksCiAgICAgICAgICAgICAgICAgbWVkaWFueXJCVCA9IG1lZGlhbihZRUFSKSwKICAgICAgICAgICAgICAgICBtZWFueXJCVCA9IG1lYW4oWUVBUikpLCAKICAgICAgICAgICAgIGJ5ID0gLihyYXJlZnlJRCldICMgbnVtYmVyIG9mIHllYXJzIGluIHRpbWUtc2VyaWVzCgp0cmVuZHMgPC0gbWVyZ2UodHJlbmRzLCB0cmVuZHMyKSAjIG1lcmdlIGluIHRvdGFsIEogYW5kIEhvcm4tTW9yaXNpdGEKdHJlbmRzIDwtIG1lcmdlKHRyZW5kcywgdHJlbmRzMykKdHJlbmRzIDwtIG1lcmdlKHRyZW5kcywgdHJlbmRzNSkKdHJlbmRzIDwtIG1lcmdlKHRyZW5kcywgdHJlbmRzNikKdHJlbmRzIDwtIG1lcmdlKHRyZW5kcywgdHJlbmRzNykKdHJlbmRzIDwtIG1lcmdlKHRyZW5kcywgbnlyQlQpCmBgYAoKQWRkIGNvdmFyaWF0ZXMKYGBge3IgYWRkIGNvdmFyaWF0ZSBkYXRhfQojIGFkZCBjb3ZhcmlhdGVzCnRyZW5kcyA8LSBtZXJnZSh0cmVuZHMsIHRlbXBlcmF0dXJlWywgLihyYXJlZnlJRCwgdGVtcGF2ZSwgdGVtcGF2ZV9tZXRhYiwgdGVtcHRyZW5kLCBzZWFzKV0sIGFsbC54ID0gVFJVRSwgYnkgPSAncmFyZWZ5SUQnKSAjIHRlbXBlcmF0dXJlIGF2ZSwgYXZlIG1ldGFib2xpYywgdHJlbmQsIGFuZCBzZWFzb25hbGl0eQp0cmVuZHMgPC0gbWVyZ2UodHJlbmRzLCBtaWNyb2NsaW1bLCAuKHJhcmVmeUlELCBtaWNyb2NsaW0gPSBUZW1wX3NkMjBrbSldLCBhbGwueCA9IFRSVUUsIGJ5ID0gJ3JhcmVmeUlEJykgIyBtaWNyb2NsaW1hdGVzCnRyZW5kcyA8LSBtZXJnZSh0cmVuZHMsIG5wcCwgYWxsLnggPSBUUlVFLCBieSA9ICdyYXJlZnlJRCcpICMgbnBwCnRyZW5kcyA8LSBtZXJnZSh0cmVuZHMsIGJzWywgLihyYXJlZnlJRCwgbWFzc19tZWFuX3dlaWdodCwgbWFzc19zZF93ZWlnaHQpXSwgYWxsLnggPSBUUlVFKSAjIGJvZHkgc2l6ZSBtYXNzIChnKQp0cmVuZHMgPC0gbWVyZ2UodHJlbmRzLCBzcGVlZFssIC4ocmFyZWZ5SUQsIHNwZWVkX21lYW5fd2VpZ2h0LCBzcGVlZF9zZF93ZWlnaHQpXSwgYWxsLnggPSBUUlVFKSAjIHNwZWVkIChrbS9ocikKdHJlbmRzIDwtIG1lcmdlKHRyZW5kcywgbHNwWywgLihyYXJlZnlJRCwgbGlmZXNwYW5fbWVhbl93ZWlnaHQsIGxpZmVzcGFuX3NkX3dlaWdodCldLCBhbGwueCA9IFRSVUUpICMgbGlmZXNwYW4gKHlyKQp0cmVuZHMgPC0gbWVyZ2UodHJlbmRzLCBjdGlbLCAuKHJhcmVmeUlELCB0aGVybWFsX2JpYXMpXSwgYWxsLnggPSBUUlVFKSAjIHRoZXJtYWwgYmlhcyAoZGVnQykKdHJlbmRzIDwtIG1lcmdlKHRyZW5kcywgY29uc2ZyYWMsIGFsbC54ID0gVFJVRSkgIyBmcmFjdGlvbiBjb25zdW1lcnMKdHJlbmRzIDwtIG1lcmdlKHRyZW5kcywgcmljaCwgYWxsLnggPSBUUlVFKSAjIHNwZWNpZXMgcmljaG5lc3MKdHJlbmRzIDwtIG1lcmdlKHRyZW5kcywgZW5kb2ZyYWMsIGFsbC54ID0gVFJVRSkgIyBlbmRvdGhlcm0gdnMuIGVjdG90aGVybQp0cmVuZHMgPC0gbWVyZ2UodHJlbmRzLCBodW1hblssIC4ocmFyZWZ5SUQsIGh1bWFuX2Jvd2xlciA9IGF0YywgaHVtYW5fdmVudGVyID0gaGZwLCBodW1hbl9oYWxwZXJuID0gaGltcCldLCBhbGwueCA9IFRSVUUpICMgaHVtYW4gaW1wYWN0CnRyZW5kcyA8LSBtZXJnZSh0cmVuZHMsIHZlZ1ssIC4ocmFyZWZ5SUQsIHZlZyA9IHZlZyldLCBhbGwueCA9IFRSVUUpICMgdmVnZXRhdGlvbiBpbmRleAp0cmVuZHNbUkVBTE0gPT0gJ01hcmluZScsIHZlZyA6PSAwXSAjIHZlZyBpbmRleCBpcyAwIGF0IHNlYQpgYGAKCkRvIHNvbWUgYmFzaWMgY2hlY2tzIG9mIHRoZSB0dXJub3ZlciBjYWxjdWxhdGlvbnMKYGBge3IgYmFzaWMgY2hlY2tzfQojIGJhc2ljIGNoZWNrcwp0cmVuZHMKdHJlbmRzWywgLihtaW5KdHUgPSBtaW4oSnR1dHJlbmQpLCBtYXhKdHUgPSBtYXgoSnR1dHJlbmQpLCBtaW5KYmUgPSBtaW4oSmJldGF0cmVuZCksIG1heEpiZSA9IG1heChKYmV0YXRyZW5kKSwgCiAgICAgICAgICAgbWluSG8gPSBtaW4oSG9ybnRyZW5kLCBuYS5ybSA9IFRSVUUpLCBtYXhIbyA9IG1heChIb3JudHJlbmQsIG5hLnJtID0gVFJVRSkpLCBieSA9IFJFQUxNXQp0cmVuZHNbLCAuKG5KdHUgPSBzdW0oSnR1dHJlbmQgPCAwKSksIGJ5ID0gUkVBTE1dICMgd2h5IGFyZSBzb21lIHR1cm5vdmVyIHRyZW5kcyA8IDA/IGZpcnN0IHllYXIgbW9yZSBkaXZlcmdlZCB0aGFuIGZ1dHVyZSB5ZWFycwp0cmVuZHNbLCAuKG5KID0gc3VtKEp0dXRyZW5kID4gMCkpLCBieSA9IFJFQUxNXQoKIyBudW1iZXIgb2Ygc3BlY2llcwp0cmVuZHNbLCBzdW1tYXJ5KE5zcHApXQp0cmVuZHNbLCBwbG90KE5zcHAsIEp0dXRyZW5kLCBsb2cgPSAneCcpXQpgYGAKClJlbW92ZSBzdHVkaWVzIHdpdGggb25seSAxIHNwZWNpZXMKYGBge3IgcmVtb3ZlIDEtc3BwIHN0dWRpZXN9Cm5yb3codHJlbmRzKQp0cmVuZHMgPC0gdHJlbmRzW05zcHAgPiAxLCBdCm5yb3codHJlbmRzKQpgYGAKClR1cm5vdmVyIGNhbGN1bGF0aW9ucyBhcmUgY29ycmVsYXRlZCwgdGhvdWdoIGxlc3Mgc28gZm9yIEhvcm4KYGBge3IgYmFzaWMgcGFpcndpc2UgZ3JhcGhzIG9mIHR1cm5vdmVyIG1ldHJpY3N9CiMgYXJlIHR1cm5vdmVyIGNhbGN1bGF0aW9ucyBjb3JyZWxhdGVkPwpnZ3Bsb3QodHJlbmRzLCBhZXMoSmJldGF0cmVuZCwgSnR1dHJlbmQpKSArCiAgICBnZW9tX3BvaW50KGFscGhhID0gMC4zKSArCiAgICBnZW9tX3Ntb290aCgpCgpnZ3Bsb3QodHJlbmRzLCBhZXMoSmJldGF0cmVuZCwgSG9ybnRyZW5kKSkgKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykgKwogICAgZ2VvbV9zbW9vdGgoKQoKYGBgClRlbXBvcmFsIHR1cm5vdmVyIGlzIG5vdCBhbGwgdGhhdCBjb3JyZWxhdGVkIGJldHdlZW4gaW5jbHVkaW5nIGZpcnN0IHllYXIgb3Igbm90LgpgYGB7ciB0dXJub3ZlciBtZXRyaWNzIHdpdGggYW5kIHdpdGhvdXQgZmlyc3QgeWVhcn0KZ2dwbG90KHRyZW5kcywgYWVzKEp0dXRyZW5kLCBKdHV0cmVuZHJlbTApKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykgKwogIGdlb21fc21vb3RoKCkgKwogIGdlb21fYWJsaW5lKGEgPSAwLCBiID0gMSkKCmdncGxvdCh0cmVuZHMsIGFlcyhKYmV0YXRyZW5kLCBKYmV0YXRyZW5kcmVtMCkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC4zKSArCiAgZ2VvbV9zbW9vdGgoKSArCiAgZ2VvbV9hYmxpbmUoYSA9IDAsIGIgPSAxKQoKZ2dwbG90KHRyZW5kcywgYWVzKEhvcm50cmVuZCwgSG9ybnRyZW5kcmVtMCkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC4zKSArCiAgZ2VvbV9zbW9vdGgoKSArCiAgZ2VvbV9hYmxpbmUoYSA9IDAsIGIgPSAxKQoKYGBgCgojIyBDb21wYXJlIGNvdmFyaWF0ZXMgYWNyb3NzIHJlYWxtcwpgYGB7ciBjb21wYXJlIGFjcm9zcyByZWFsbXMsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD05fQppIDwtIHRyZW5kc1ssICFkdXBsaWNhdGVkKHJhcmVmeUlEKV07IHN1bShpKQpwYXIobWZyb3c9Yyg1LDMpKQpiZWFucGxvdChyYXJlZnlJRF95IH4gUkVBTE0sIGRhdGEgPSB0cmVuZHNbaSxdLCB3aGF0ID0gYygxLDEsMSwxKSwgY29sID0gYygiI0NBQjJENiIsICIjMzNBMDJDIiwgIiNCMkRGOEEiKSwgYm9yZGVyID0gIiNDQUIyRDYiLCB5bGFiID0gJ0xhdGl0dWRlIChkZWdOKScsIGxsID0gMC4wNSkKYmVhbnBsb3QodGVtcGF2ZSB+IFJFQUxNLCBkYXRhID0gdHJlbmRzW2ksXSwgd2hhdCA9IGMoMSwxLDEsMSksIGNvbCA9IGMoIiNDQUIyRDYiLCAiIzMzQTAyQyIsICIjQjJERjhBIiksIGJvcmRlciA9ICIjQ0FCMkQ2IiwgeWxhYiA9ICdUZW1wZXJhdHVyZSAoZGVnQyknLCBsbCA9IDAuMDUpCmJlYW5wbG90KHRlbXBhdmVfbWV0YWIgfiBSRUFMTSwgZGF0YSA9IHRyZW5kc1tpLF0sIHdoYXQgPSBjKDEsMSwxLDEpLCBjb2wgPSBjKCIjQ0FCMkQ2IiwgIiMzM0EwMkMiLCAiI0IyREY4QSIpLCBib3JkZXIgPSAiI0NBQjJENiIsIHlsYWIgPSAnTWV0YWJvbGljIFRlbXBlcmF0dXJlIChkZWdDKScsIGxsID0gMC4wNSwgYncgPSAnbnJkMCcpICMgbnJkMCBiYW5kd2lkdGggdG8gY2FsY3VsYXRpb24gZ2FwCmJlYW5wbG90KHNlYXMgfiBSRUFMTSwgZGF0YSA9IHRyZW5kc1tpLF0sIHdoYXQgPSBjKDEsMSwxLDEpLCBjb2wgPSBjKCIjQ0FCMkQ2IiwgIiMzM0EwMkMiLCAiI0IyREY4QSIpLCBib3JkZXIgPSAiI0NBQjJENiIsIHlsYWIgPSAnU2Vhc29uYWxpdHkgKGRlZ0MpJywgbGwgPSAwLjA1KQpiZWFucGxvdChtaWNyb2NsaW0gfiBSRUFMTSwgZGF0YSA9IHRyZW5kc1tpLF0sIHdoYXQgPSBjKDEsMSwxLDEpLCBjb2wgPSBjKCIjQ0FCMkQ2IiwgIiMzM0EwMkMiLCAiI0IyREY4QSIpLCBib3JkZXIgPSAiI0NBQjJENiIsIHlsYWIgPSAnTWljcm9jbGltYXRlcyAoZGVnQyknLCBsbCA9IDAuMDUpCmJlYW5wbG90KHRlbXB0cmVuZCB+IFJFQUxNLCBkYXRhID0gdHJlbmRzW2ksXSwgd2hhdCA9IGMoMSwxLDEsMSksIGNvbCA9IGMoIiNDQUIyRDYiLCAiIzMzQTAyQyIsICIjQjJERjhBIiksIGJvcmRlciA9ICIjQ0FCMkQ2IiwgeWxhYiA9ICdUZW1wZXJhdHVyZSB0cmVuZCAoZGVnQy95ciknLCBsbCA9IDAuMDUpCmJlYW5wbG90KG1hc3NfbWVhbl93ZWlnaHQgfiBSRUFMTSwgZGF0YSA9IHRyZW5kc1tpLF0sIHdoYXQgPSBjKDEsMSwxLDEpLCBjb2wgPSBjKCIjQ0FCMkQ2IiwgIiMzM0EwMkMiLCAiI0IyREY4QSIpLCBib3JkZXIgPSAiI0NBQjJENiIsIHlsYWIgPSAnTWFzcyAoZyknLCBsbCA9IDAuMDUsIGxvZyA9ICd5JykKYmVhbnBsb3Qoc3BlZWRfbWVhbl93ZWlnaHQgKzEgfiBSRUFMTSwgZGF0YSA9IHRyZW5kc1tpLF0sIHdoYXQgPSBjKDEsMSwxLDEpLCBjb2wgPSBjKCIjQ0FCMkQ2IiwgIiMzM0EwMkMiLCAiI0IyREY4QSIpLCBib3JkZXIgPSAiI0NBQjJENiIsIHlsYWIgPSAnU3BlZWQgKGttL2hyKScsIGxsID0gMC4wNSwgbG9nID0gJ3knKQpiZWFucGxvdChsaWZlc3Bhbl9tZWFuX3dlaWdodCB+IFJFQUxNLCBkYXRhID0gdHJlbmRzW2ksXSwgd2hhdCA9IGMoMSwxLDEsMSksIGNvbCA9IGMoIiNDQUIyRDYiLCAiIzMzQTAyQyIsICIjQjJERjhBIiksIGJvcmRlciA9ICIjQ0FCMkQ2IiwgeWxhYiA9ICdMaWZlc3BhbiAoeXIpJywgbGwgPSAwLjA1LCBsb2cgPSAneScpCiNiZWFucGxvdChjb25zZnJhYyB+IFJFQUxNLCBkYXRhID0gdHJlbmRzW2ksXSwgd2hhdCA9IGMoMSwxLDEsMSksIGNvbCA9IGMoIiNDQUIyRDYiLCAiIzMzQTAyQyIsICIjQjJERjhBIiksIGJvcmRlciA9ICIjQ0FCMkQ2IiwgeWxhYiA9ICdDb25zdW1lcnMgKGZyYWN0aW9uKScsIGxsID0gMC4wNSwgbG9nID0gJycpICMgdG9vIHNwYXJzZQojYmVhbnBsb3QoZW5kb2ZyYWMgfiBSRUFMTSwgZGF0YSA9IHRyZW5kc1tpLF0sIHdoYXQgPSBjKDEsMSwxLDEpLCBjb2wgPSBjKCIjQ0FCMkQ2IiwgIiMzM0EwMkMiLCAiI0IyREY4QSIpLCBib3JkZXIgPSAiI0NBQjJENiIsIHlsYWIgPSAnRW5kb3RoZXJtcyAoZnJhY3Rpb24pJywgbGwgPSAwLjA1LCBsb2cgPSAnJykgIyB0b28gc3BhcnNlCmJlYW5wbG90KE5zcHAgfiBSRUFMTSwgZGF0YSA9IHRyZW5kc1tpLF0sIHdoYXQgPSBjKDEsMSwxLDEpLCBjb2wgPSBjKCIjQ0FCMkQ2IiwgIiMzM0EwMkMiLCAiI0IyREY4QSIpLCBib3JkZXIgPSAiI0NBQjJENiIsIHlsYWIgPSAnTnVtYmVyIG9mIHNwZWNpZXMnLCBsbCA9IDAuMDUsIGxvZyA9ICd5JykKYmVhbnBsb3QodGhlcm1hbF9iaWFzIH4gUkVBTE0sIGRhdGEgPSB0cmVuZHNbaSAmICFpcy5uYSh0aGVybWFsX2JpYXMpLF0sIHdoYXQgPSBjKDEsMSwxLDEpLCBjb2wgPSBjKCIjQ0FCMkQ2IiwgIiMzM0EwMkMiLCAiI0IyREY4QSIpLCBib3JkZXIgPSAiI0NBQjJENiIsIHlsYWIgPSAnVGhlcm1hbCBiaWFzIChkZWdDKScsIGxsID0gMC4wNSkKYmVhbnBsb3QobnBwIH4gUkVBTE0sIGRhdGEgPSB0cmVuZHNbaSxdLCB3aGF0ID0gYygxLDEsMSwxKSwgY29sID0gYygiI0NBQjJENiIsICIjMzNBMDJDIiwgIiNCMkRGOEEiKSwgYm9yZGVyID0gIiNDQUIyRDYiLCB5bGFiID0gJ05QUCcsIGxsID0gMC4wNSkKYmVhbnBsb3QodmVnIH4gUkVBTE0sIGRhdGEgPSB0cmVuZHNbaSAmIFJFQUxNICE9J01hcmluZScsXSwgd2hhdCA9IGMoMSwxLDEsMSksIGNvbCA9IGMoIiNDQUIyRDYiLCAiIzMzQTAyQyIsICIjQjJERjhBIiksIGJvcmRlciA9ICIjQ0FCMkQ2IiwgeWxhYiA9ICdOUFAnLCBsbCA9IDAuMDUpCgpgYGAKCk1hcmluZSBhcmUgaW4gZ2VuZXJhbGx5IHdhcm1lciBsb2NhdGlvbnMgKHNlYXdhdGVyIGRvZXNuJ3QgZnJlZXplKQpNYXJpbmUgaGF2ZSBtdWNoIGxvd2VyIHNlYXNvbmFsaXR5LgpNYXJpbmUgYW5kIGZyZXNod2F0ZXIgaGF2ZSBzb21lIHZlcnkgc21hbGwgbWFzc2VzIChwbGFua3RvbiksIGJ1dCBtdWNoIG9mIGRhdGFzZXQgaXMgc2ltaWxhciB0byB0ZXJyZXN0cmlhbC4KTWFyaW5lIGhhcyBhIGxvdCBvZiBzbG93LCBjcmF3bGluZyBvcmdhbmlzbXMsIGJ1dCBsYW5kIGhhcyBwbGFudHMuIExhbmQgYWxzbyBoYXMgYmlyZHMgKGZhc3QpLgoKCgoKCgojIyBQbG90IHR1cm5vdmVyIHZzLiBleHBsYW5hdG9yeSB2YXJpYWJsZXMKTGluZXMgYXJlIGdncGxvdCBzbW9vdGhlciBmaXRzLgpgYGB7ciBwbG90IHR1cm5vdmVyIHYgdGVtcCB0cmVuZCwgZWNobz1GQUxTRSwgZmlnLmhlaWdodCA9IDE2LCBmaWcud2lkdGggPSA5LH0KCnAxIDwtIGdncGxvdCh0cmVuZHMsIGFlcyhSRUFMTSwgSnR1dHJlbmQpKSArCiAgZ2VvbV9ib3hwbG90KG5hLnJtID0gVFJVRSkgKyAKICBsYWJzKHggPSAnUmVhbG0nLCB5ID0gJ0phY2NhcmQgdHVybm92ZXIgdGVtcG9yYWwgdHJlbmQnKQoKcDIgPC0gZ2dwbG90KHRyZW5kcywgYWVzKHRlbXBhdmUsIEp0dXRyZW5kLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBSRUFMTSksIHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIpLCBuYS5ybSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJykgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnVGVtcGVyYXR1cmUgKMKwQyknLCB5ID0gJ0phY2NhcmQgdHVybm92ZXIgdGVtcG9yYWwgdHJlbmQnKQoKcDMgPC0gZ2dwbG90KHRyZW5kcywgYWVzKHRlbXBhdmVfbWV0YWIsIEp0dXRyZW5kLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBSRUFMTSksIHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIpLCBuYS5ybSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJykgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnTWV0YWJvbGljIHRlbXBlcmF0dXJlICjCsEMpJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnA0IDwtIGdncGxvdCh0cmVuZHMsIGFlcyhzZWFzLCBKdHV0cmVuZCwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gUkVBTE0pLCBzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiKSwgbmEucm0gPSBUUlVFLCBjb2xvciA9ICdibGFjaycpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgbGFicyh4ID0gJ1NlYXNvbmFsaXR5ICjCsEMpJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnA1IDwtIGdncGxvdCh0cmVuZHMsIGFlcyhtaWNyb2NsaW0sIEp0dXRyZW5kLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBSRUFMTSksIHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIpLCBuYS5ybSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJykgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBzY2FsZV94X2xvZzEwKCkgKwogIGxhYnMoeCA9ICdNaWNyb2NsaW1hdGUgYXZhaWxhYmlsaXR5ICjCsEMpJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnA2IDwtIGdncGxvdCh0cmVuZHMsIGFlcyhtYXNzX21lYW5fd2VpZ2h0LCBKdHV0cmVuZCwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gUkVBTE0pLCBzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiKSwgbmEucm0gPSBUUlVFLCBjb2xvciA9ICdibGFjaycpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgc2NhbGVfeF9sb2cxMCgpICsKICBsYWJzKHggPSAnTWFzcyAoZykpJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnA3IDwtIGdncGxvdCh0cmVuZHMsIGFlcyhzcGVlZF9tZWFuX3dlaWdodCsxLCBKdHV0cmVuZCwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gUkVBTE0pLCBzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiKSwgbmEucm0gPSBUUlVFLCBjb2xvciA9ICdibGFjaycpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgc2NhbGVfeF9sb2cxMCgpICsKICBsYWJzKHggPSAnU3BlZWQgKGttIC8gaHIpKScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgpwOCA8LSBnZ3Bsb3QodHJlbmRzLCBhZXMobGlmZXNwYW5fbWVhbl93ZWlnaHQsIEp0dXRyZW5kLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBSRUFMTSksIHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIpLCBuYS5ybSA9IFRSVUUsIGNvbG9yID0gJ2JsYWNrJykgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBzY2FsZV94X2xvZzEwKCkgKwogIGxhYnMoeCA9ICdMaWZlc3BhbiAoeXIpKScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgpwOSA8LSBnZ3Bsb3QodHJlbmRzLCBhZXMoY29uc2ZyYWMsIEp0dXRyZW5kLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBSRUFMTSksIHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIsIGsgPSAzKSwgbmEucm0gPSBUUlVFLCBjb2xvciA9ICdibGFjaycpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgbGFicyh4ID0gJ0ZyYWN0aW9uIGNvbnN1bWVycycsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgpwMTAgPC0gZ2dwbG90KHRyZW5kcywgYWVzKGVuZG9mcmFjLCBKdHV0cmVuZCwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gUkVBTE0pLCBzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiLCBrID0gMyksIG5hLnJtID0gVFJVRSwgY29sb3IgPSAnYmxhY2snKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIGxhYnMoeCA9ICdGcmFjdGlvbiBlbmRvdGhlcm1zJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnAxMSA8LSBnZ3Bsb3QodHJlbmRzLCBhZXMoTnNwcCwgSnR1dHJlbmQsIHNpemUgPSBueXJCVCkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IFJFQUxNKSwgc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSwgY29sb3IgPSAnYmxhY2snKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIHNjYWxlX3hfbG9nMTAoKSArCiAgbGFicyh4ID0gJ051bWJlciBvZiBzcGVjaWVzJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnAxMiA8LSBnZ3Bsb3QodHJlbmRzLCBhZXModGhlcm1hbF9iaWFzLCBKdHV0cmVuZCwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gUkVBTE0pLCBzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiKSwgbmEucm0gPSBUUlVFLCBjb2xvciA9ICdibGFjaycpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgbGFicyh4ID0gJ1RoZXJtYWwgYmlhcyAowrBDKScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgpwMTMgPC0gZ2dwbG90KHRyZW5kcywgYWVzKG5wcCwgSnR1dHJlbmQsIHNpemUgPSBueXJCVCkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IFJFQUxNKSwgc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSwgY29sb3IgPSAnYmxhY2snKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIHNjYWxlX3hfbG9nMTAoKSArCiAgbGFicyh4ID0gJ05ldCBwcmltYXJ5IHByb2R1Y3Rpdml0eSAobWcgQyAvIG0yIC8gZGF5KScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgpwMTQgPC0gZ2dwbG90KHRyZW5kcywgYWVzKHZlZywgSnR1dHJlbmQsIGNvbG9yID0gUkVBTE0sIHNpemUgPSBueXJCVCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAwLjIsIGFscGhhID0gMC41LCBuYS5ybSA9IFRSVUUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gJ2dhbScsIGZvcm11bGEgPSB5IH4gcyh4LCBicyA9ICJjcyIsIGsgPSA1KSwgbmEucm0gPSBUUlVFKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIGxhYnMoeCA9ICdWZWdldGF0aW9uIHNjb3JlJywgeSA9ICdKYWNjYXJkIHR1cm5vdmVyIHRlbXBvcmFsIHRyZW5kJykKCnAxNSA8LSBnZ3Bsb3QodHJlbmRzLCBhZXMoaHVtYW5fYm93bGVyLCBKdHV0cmVuZCwgY29sb3IgPSBSRUFMTSwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiwgayA9IDUpLCBuYS5ybSA9IFRSVUUpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iU2V0MSIpICsgCiAgbGFicyh4ID0gJ0Jvd2xlciBodW1hbiBpbXBhY3Qgc2NvcmUnLCB5ID0gJ0phY2NhcmQgdHVybm92ZXIgdGVtcG9yYWwgdHJlbmQnKQoKcDE2IDwtIGdncGxvdCh0cmVuZHMsIGFlcyhodW1hbl92ZW50ZXIsIEp0dXRyZW5kLCBjb2xvciA9IFJFQUxNLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiLCBrID0gNSksIG5hLnJtID0gVFJVRSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnc2NhbGVkIEh1bWFuIGltcGFjdCBzY29yZSAoVmVudGVyKScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgpwMTcgPC0gZ2dwbG90KHRyZW5kcywgYWVzKGh1bWFuX2hhbHBlcm4sIEp0dXRyZW5kLCBjb2xvciA9IFJFQUxNLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiLCBrID0gNSksIG5hLnJtID0gVFJVRSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnc2NhbGVkIEh1bWFuIGltcGFjdCBzY29yZSAoSGFscGVybiknLCB5ID0gJ0phY2NhcmQgdHVybm92ZXIgdGVtcG9yYWwgdHJlbmQnKQoKcDE4IDwtIGdncGxvdCh0cmVuZHMsIGFlcyh0ZW1wdHJlbmQsIEp0dXRyZW5kLCBjb2xvciA9IFJFQUxNLCBzaXplID0gbnlyQlQpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMC4yLCBhbHBoYSA9IDAuNSwgbmEucm0gPSBUUlVFKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdnYW0nLCBmb3JtdWxhID0geSB+IHMoeCwgYnMgPSAiY3MiKSwgbmEucm0gPSBUUlVFKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGU9IlNldDEiKSArIAogIGxhYnMoeCA9ICdUZW1wZXJhdHVyZSB0cmVuZCAowrBDL3lyKScsIHkgPSAnSmFjY2FyZCB0dXJub3ZlciB0ZW1wb3JhbCB0cmVuZCcpCgojIEphY2NhcmQgdG90YWwgdHJlbmQgdnMuIHRlbXBlcmF0dXJlIHRyZW5kIChhY3Jvc3MgYWxsIHllYXJzKQpwMTkgPC0gZ2dwbG90KHRyZW5kcywgYWVzKHRlbXB0cmVuZCwgSmJldGF0cmVuZCwgY29sb3IgPSBSRUFMTSwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnVGVtcGVyYXR1cmUgdHJlbmQgKMKwQy95ZWFyKScsIHkgPSAnSmFjY2FyZCB0b3RhbCB0ZW1wb3JhbCB0cmVuZCcpCgoKIyBIb3JuLU1vcmlzaXRhIHR1cm5vdmVyIHRyZW5kIHZzLiB0ZW1wZXJhdHVyZSB0cmVuZCAoYWNyb3NzIGFsbCB5ZWFycykKcDIwIDwtIGdncGxvdCh0cmVuZHMsIGFlcyh0ZW1wdHJlbmQsIEhvcm50cmVuZCwgY29sb3IgPSBSRUFMTSwgc2l6ZSA9IG55ckJUKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMiwgYWxwaGEgPSAwLjUsIG5hLnJtID0gVFJVRSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnZ2FtJywgZm9ybXVsYSA9IHkgfiBzKHgsIGJzID0gImNzIiksIG5hLnJtID0gVFJVRSkgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlPSJTZXQxIikgKyAKICBsYWJzKHggPSAnVGVtcGVyYXR1cmUgdHJlbmQgKMKwQy95ZWFyKScsIHkgPSAnTW9yaXNpdGEtSG9ybiB0ZW1wb3JhbCB0dXJub3ZlcicpCgoKZ3JpZC5hcnJhbmdlKHAxLCBwMiwgcDMsIHA0LCBwNSwgcDYsIHA3LCBwOCwgcDksIHAxMCwgcDExLCBwMTIsIHAxMywgcDE0LCBwMTUsIHAxNiwgcDE3LCBwMTgsIHAxOSwgcDIwLCBuY29sID0gMikKYGBgCgpTdHJvbmcgdHJlbmRzIHdpdGggdGVtcGVyYXR1cmUgY2hhbmdlLCBidXQgdHJlbmRzIGFyZSBwcmV0dHkgc3ltbWV0cmljIGFyb3VuZCBubyB0cmVuZCBpbiB0ZW1wZXJhdHVyZSwgd2hpY2ggaW1wbGllcyB3YXJtaW5nIG9yIGNvb2xpbmcgZHJpdmVzIHNpbWlsYXIgZGVncmVlIG9mIGNvbW11bml0eSB0dXJub3Zlci4KU29tZSBpbmRpY2F0aW9uIG9mIGxlc3MgdHVybm92ZXIgZm9yIGxhcmdlciBvcmdhbmlzbXMgKG1hc3MpCkhpZ2hlciB0dXJub3ZlciBvbiBsYW5kIHdpdGggaGlnaGVyIHNlYXNvbmFsaXR5PwpNb3JlIHR1cm5vdmVyIGZvciBzaG9ydGVyLWxpdmVkIG9yZ2FuaXNtcz8KTm8gcmVhbGx5IGNsZWFyIGRpZmZlcmVuY2VzIGFtb25nIHJlYWxtcy4KCiMjIyBXcml0ZSBvdXQKYGBge3Igd3JpdGUgb3V0fQp3cml0ZS5jc3YodHJlbmRzLCBnemZpbGUoJ291dHB1dC90dXJub3Zlcl93X2NvdmFyaWF0ZXMuY3N2Lmd6JyksIHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCgojIyMgVXNlZnVsIHZhcmlhYmxlcwpgYGB7ciB1c2VmdWwgdmFyc30KIyByZWFsbSB0aGF0IGNvbWJpbmVkIFRlcnJlc3RyaWFsIGFuZCBGcmVzaHdhdGVyLCBmb3IgaW50ZXJhY3Rpbmcgd2l0aCBodW1hbiBpbXBhY3QKdHJlbmRzWywgUkVBTE0yIDo9IFJFQUxNXQpsZXZlbHModHJlbmRzJFJFQUxNMikgPSBsaXN0KFRlcnJGcmVzaCA9ICJGcmVzaHdhdGVyIiwgVGVyckZyZXNoID0gIlRlcnJlc3RyaWFsIiwgTWFyaW5lID0gIk1hcmluZSIpCgojIGdyb3VwIE1hcmluZSBpbnZlcnRlYnJhdGVzL3BsYW50cyBpbiB3aXRoIEFsbAp0cmVuZHNbLCB0YXhhX21vZDIgOj0gdGF4YV9tb2RdCnRyZW5kc1t0YXhhX21vZCA9PSAnTWFyaW5lIGludmVydGVicmF0ZXMvcGxhbnRzJywgdGF4YV9tb2QyIDo9ICdBbGwnXQpgYGAKCgojIyMgTG9nLXRyYW5zZm9ybSBzb21lIHZhcmlhYmxlcywgdGhlbiBjZW50ZXIgYW5kIHNjYWxlLiAKYGBgIHtyIGNlbnRlciBhbmQgc2NhbGV9CnRyZW5kc1ssIHRlbXBhdmUuc2MgOj0gc2NhbGUodGVtcGF2ZSldCnRyZW5kc1ssIHRlbXBhdmVfbWV0YWIuc2MgOj0gc2NhbGUodGVtcGF2ZV9tZXRhYildCnRyZW5kc1ssIHNlYXMuc2MgOj0gc2NhbGUoc2VhcyldCnRyZW5kc1ssIG1pY3JvY2xpbS5zYyA6PSBzY2FsZShsb2cobWljcm9jbGltKSldCnRyZW5kc1ssIHRlbXB0cmVuZC5zYyA6PSBzY2FsZSh0ZW1wdHJlbmQsIGNlbnRlciA9IEZBTFNFKV0KdHJlbmRzWywgdGVtcHRyZW5kX2Ficy5zYyA6PSBzY2FsZShhYnModGVtcHRyZW5kKSwgY2VudGVyID0gRkFMU0UpXSAjIGRvIG5vdCBjZW50ZXIsIHNvIHRoYXQgMCBpcyBzdGlsbCAwIHRlbXBlcmF0dXJlIGNoYW5nZQp0cmVuZHNbLCBtYXNzLnNjIDo9IHNjYWxlKGxvZyhtYXNzX21lYW5fd2VpZ2h0KSldCnRyZW5kc1ssIHNwZWVkLnNjIDo9IHNjYWxlKGxvZyhzcGVlZF9tZWFuX3dlaWdodCsxKSldCnRyZW5kc1ssIGxpZmVzcGFuLnNjIDo9IHNjYWxlKGxvZyhsaWZlc3Bhbl9tZWFuX3dlaWdodCkpXQp0cmVuZHNbLCBjb25zdW1lcmZyYWMuc2MgOj0gc2NhbGUoY29uc2ZyYWMpXQp0cmVuZHNbLCBlbmRvdGhlcm1mcmFjLnNjIDo9IHNjYWxlKGVuZG9mcmFjKV0KdHJlbmRzWywgbnNwcC5zYyA6PSBzY2FsZShsb2coTnNwcCkpXQp0cmVuZHNbLCB0aGVybWFsX2JpYXMuc2MgOj0gc2NhbGUodGhlcm1hbF9iaWFzKV0KdHJlbmRzWywgbnBwLnNjIDo9IHNjYWxlKGxvZyhucHApKV0KdHJlbmRzWywgdmVnLnNjIDo9IHNjYWxlKGxvZyh2ZWcrMSkpXQp0cmVuZHNbLCBodW1hbl9ib3dsZXIuc2MgOj0gc2NhbGUobG9nKGh1bWFuX2Jvd2xlcisxKSksIGJ5ID0gUkVBTE0yXSAjIHNlcGFyYXRlIHNjYWxpbmcgYnkgcmVhbG0KdHJlbmRzW1JFQUxNMiA9PSAnVGVyckZyZXNoJywgaHVtYW5fZm9vdHByaW50LnNjIDo9IHNjYWxlKGxvZyhodW1hbl92ZW50ZXIrMSkpXQp0cmVuZHNbUkVBTE0yID09ICdNYXJpbmUnLCBodW1hbl9mb290cHJpbnQuc2MgOj0gc2NhbGUobG9nKGh1bWFuX2hhbHBlcm4pKV0KYGBgCgoKIyMjIERvIHRoZSB2YXJpYWJsZXMgbG9vayBvaz8KIyMjIyBVbnNjYWxlZApgYGB7ciBoaXN0b2dyYW1zIHVuc2NhbGVkLCBmaWcuaGVpZ2h0ID0gOX0KIyBoaXN0b2dyYW1zIHRvIGV4YW1pbmUKY2V4bWFpbiA9IDAuNgpwYXIobWZyb3cgPSBjKDUsNCkpCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KG1pbnlyQlQsIG1haW4gPSAnU3RhcnQgeWVhcicsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdChtYXh5ckJUIC0gbWlueXJCVCwgbWFpbiA9ICdEdXJhdGlvbiAoeWVhcnMpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KG55ckJULCBtYWluID0gJ051bWJlciBvZiBzYW1wbGVkIHllYXJzJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KG1hc3NfbWVhbl93ZWlnaHQsIG1haW4gPSAnTWFzcyAoZyknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3Qoc3BlZWRfbWVhbl93ZWlnaHQsIG1haW4gPSAnU3BlZWQgKGttL2hyKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdChsaWZlc3Bhbl9tZWFuX3dlaWdodCwgbWFpbiA9ICdMaWZlc3BhbiAoeXIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHRlbXBhdmVfbWV0YWIsIG1haW4gPSAnTWV0YWJvbGljIHRlbXBlcmF0dXJlICjCsEMpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KGNvbnNmcmFjLCBtYWluID0gJ0NvbnN1bWVycyAoZnJhY3Rpb24pJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KGVuZG9mcmFjLCBtYWluID0gJ0VuZG90aGVybXMgKGZyYWN0aW9uKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdCh0ZW1wYXZlLCBtYWluID0gJ0Vudmlyb25tZW50YWwgdGVtcGVyYXR1cmUgKMKwQyknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QodGVtcHRyZW5kLCBtYWluID0gJ1RlbXBlcmF0dXJlIHRyZW5kICjCsEMveXIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHNlYXMsIG1haW4gPSAnU2Vhc29uYWxpdHkgKMKwQyknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QobWljcm9jbGltLCBtYWluID0gJ01pY3JvY2xpbWF0ZXMgKMKwQyknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QoTnNwcCwgbWFpbiA9ICdTcGVjaWVzIHJpY2huZXNzJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHRoZXJtYWxfYmlhcywgbWFpbiA9ICdUaGVybWFsIGJpYXMgKMKwQyknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QobnBwLCBtYWluID0gJ05ldCBwcmltYXJ5IHByb2R1Y3Rpdml0eScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdCh2ZWcsIG1haW4gPSAnVmVnZXRhdGlvbiBpbmRleCcsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdChodW1hbl9ib3dsZXIsIG1haW4gPSAnSHVtYW4gaW1wYWN0IHNjb3JlIChCb3dsZXIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KGh1bWFuX3ZlbnRlciwgbWFpbiA9ICdIdW1hbiBpbXBhY3Qgc2NvcmUgKFZlbnRlciknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QoaHVtYW5faGFscGVybiwgbWFpbiA9ICdIdW1hbiBpbXBhY3Qgc2NvcmUgKEhhbHBlcm4pJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCgpgYGAKCiMjIyMgU2NhbGVkCmBgYHtyIGhpc3RvZ3JhbXMgc2NhbGVkLCBmaWcuaGVpZ2h0ID0gOX0KIyBoaXN0b2dyYW1zIHRvIGV4YW1pbmUKY2V4bWFpbiA9IDAuNgpwYXIobWZyb3cgPSBjKDUsNCkpCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHRlbXBhdmUuc2MsIG1haW4gPSAnRW52aXJvbm1lbnRhbCB0ZW1wZXJhdHVyZSAowrBDKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdCh0ZW1wYXZlX21ldGFiLnNjLCBtYWluID0gJ01ldGFib2xpYyB0ZW1wZXJhdHVyZSAowrBDKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdChzZWFzLnNjLCBtYWluID0gJ1NlYXNvbmFsaXR5ICjCsEMpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KG1pY3JvY2xpbS5zYywgbWFpbiA9ICdsb2cgTWljcm9jbGltYXRlcyAowrBDKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdCh0ZW1wdHJlbmQuc2MsIG1haW4gPSAnVGVtcGVyYXR1cmUgdHJlbmQgKMKwQy95ciknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QodGVtcHRyZW5kX2Ficy5zYywgbWFpbiA9ICdhYnMoVGVtcGVyYXR1cmUgdHJlbmQpICjCsEMveXIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KG1hc3Muc2MsIG1haW4gPSAnbG9nIE1hc3MgKGcpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHNwZWVkLnNjLCBtYWluID0gJ2xvZyBTcGVlZCAoa20vaHIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KGxpZmVzcGFuLnNjLCBtYWluID0gJ2xvZyBMaWZlc3BhbiAoeXIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KGNvbnN1bWVyZnJhYy5zYywgbWFpbiA9ICdDb25zdW1lcnMgKGZyYWN0aW9uKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdChlbmRvdGhlcm1mcmFjLnNjLCBtYWluID0gJ0VuZG90aGVybXMgKGZyYWN0aW9uKScsIGNleC5tYWluID0gY2V4bWFpbildKQppbnZpc2libGUodHJlbmRzWywgaGlzdChuc3BwLnNjLCBtYWluID0gJ2xvZyBTcGVjaWVzIHJpY2huZXNzJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KHRoZXJtYWxfYmlhcy5zYywgbWFpbiA9ICdUaGVybWFsIGJpYXMgKMKwQyknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QobnBwLnNjLCBtYWluID0gJ2xvZyBOZXQgcHJpbWFyeSBwcm9kdWN0aXZpdHknLCBjZXgubWFpbiA9IGNleG1haW4pXSkKaW52aXNpYmxlKHRyZW5kc1ssIGhpc3QodmVnLnNjLCBtYWluID0gJ2xvZyBWZWdldGF0aW9uIGluZGV4JywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KGh1bWFuX2Jvd2xlci5zYywgbWFpbiA9ICdsb2cgSHVtYW4gaW1wYWN0IHNjb3JlIChCb3dsZXIpJywgY2V4Lm1haW4gPSBjZXhtYWluKV0pCmludmlzaWJsZSh0cmVuZHNbLCBoaXN0KGh1bWFuX2Zvb3RwcmludC5zYywgbWFpbiA9ICdsb2cgSHVtYW4gaW1wYWN0IHNjb3JlIChWZW50ZXIgJiBIYWxwZXJuKScsIGNleC5tYWluID0gY2V4bWFpbildKQoKYGBgCgoKCiMjIyBDaGVjayBjb3JyZWxhdGlvbnMgYW1vbmcgdmFyaWFibGVzLiBQZWFyc29uJ3MgciBpcyBvbiB0aGUgbG93ZXIgZGlhZ29uYWwuCmBgYHtyIHBhaXJzLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTB9CnBhbmVsLmNvciA8LSBmdW5jdGlvbih4LCB5LCBkaWdpdHMgPSAyLCBwcmVmaXggPSAiIiwgY2V4LmNvciwgLi4uKQp7CiAgICB1c3IgPC0gcGFyKCJ1c3IiKTsgb24uZXhpdChwYXIodXNyKSkKICAgIHBhcih1c3IgPSBjKDAsIDEsIDAsIDEpKQogICAgciA8LSBjb3IoeCwgeSwgdXNlID0gJ3BhaXJ3aXNlLmNvbXBsZXRlLm9icycpCiAgICB0eHQgPC0gZm9ybWF0KGMociwgMC4xMjM0NTY3ODkpLCBkaWdpdHMgPSBkaWdpdHMpWzFdCiAgICB0eHQgPC0gcGFzdGUwKHByZWZpeCwgdHh0KQogICAgaWYobWlzc2luZyhjZXguY29yKSkgY2V4LmNvciA8LSAwLjgvc3Ryd2lkdGgodHh0KQogICAgdGV4dCgwLjUsIDAuNSwgdHh0KSAjLCBjZXggPSBjZXguY29yICogcikKfQpwYWlycyhmb3JtdWxhID0gfiB0ZW1wYXZlLnNjICsgdGVtcGF2ZV9tZXRhYi5zYyArIHNlYXMuc2MgKyBtaWNyb2NsaW0uc2MgKyB0ZW1wdHJlbmQuc2MgKyB0ZW1wdHJlbmRfYWJzLnNjICsgbWFzcy5zYyArIHNwZWVkLnNjICsgbGlmZXNwYW4uc2MgKyBjb25zdW1lcmZyYWMuc2MgKyBlbmRvdGhlcm1mcmFjLnNjICsgbnNwcC5zYyArIHRoZXJtYWxfYmlhcy5zYyArIG5wcC5zYyArIHZlZy5zYyArIGh1bWFuX2Jvd2xlci5zYyArIGh1bWFuX2Zvb3RwcmludC5zYywgZGF0YSA9IHRyZW5kcywgZ2FwID0gMS8xMCwgY2V4ID0gMC4yLCBjb2wgPSAnIzAwMDAwMDIyJywgbG93ZXIucGFuZWwgPSBwYW5lbC5jb3IpCgpgYGAKCk1hc3MgYW5kIGxpZmVzcGFuIGxvb2sgdGlnaHRseSBjb3JyZWxhdGVkLCBidXQgciBvbmx5IDAuNTYuLi4/ClRlbXBhdmVfbWV0YWIgYW5kIGxpZmVzcGFuIGRvbid0IGxvb2sgdGlnaHRseSBjb3JyZWxhdGVkLCBidXQgcj0gLTAuODEgClRlbXBhdmVfbWV0YWIgYW5kIHNwZWVkIGRvbid0IGxvb2sgdGlnaHRseSBjb3JyZWxhdGVkLCBidXQgcj0gLTAuODMgCkxpZmVzcGFuIGFuZCBzcGVlZCBkb24ndCBsb29rIHRpZ2h0bHkgY29ycmVsYXRlZCwgYnV0IHIgPSAwLjczCg==